package org.example.judge_contest.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.example.judge_common.entity.PageResult;
import org.example.judge_common.entity.RequestContestParams;
import org.example.judge_common.entity.RequestParams;
import org.example.judge_common.hander.RetrunMsgException;
import org.example.judge_common.util.IdWorker;
import org.example.judge_common.util.MyUtils;
import org.example.judge_contest.mapper.ContestMapper;
import org.example.judge_common.rank.RankList;
import org.example.judge_contest.service.ContestProblemService;
import org.example.judge_contest.service.ContestRegisterService;
import org.example.judge_contest.service.ContestService;
import org.example.judge_pojo.Contest;
import org.example.judge_pojo.ContestProblem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

@Service("ContestServiceImpl")
@Transactional
@Slf4j
public class ContestServiceImpl extends ServiceImpl<ContestMapper, Contest> implements ContestService {
    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    @Qualifier("ContestProblemServiceImpl")
    @Autowired
    private ContestProblemService contestProblemService;
    @Qualifier("ContestRegisterServiceImpl")
    @Autowired
    private ContestRegisterService contestRegisterService;
    @Override
    public PageResult<Contest> search(RequestContestParams params) {
        if(MyUtils.isEmpty(params.getField())){ //默认排序字段
            params.setField("create_time");
        }
        if(MyUtils.isEmpty(params.getOrder())){   //默认排序方式
            params.setOrder(RequestParams.DESC);
        }

        QueryWrapper<Contest> queryWap = new QueryWrapper<>();

        //字段模糊匹配
        if(MyUtils.isNotEmpty(params.getKey())){
            queryWap.and(new Consumer<QueryWrapper<Contest>>() { //隔离or条件
                @Override
                public void accept(QueryWrapper<Contest> problemQueryWrapper) {
                    problemQueryWrapper.like("title",params.getKey()).or().like("code",params.getKey());
                }
            });

        }

        //权限
        if(params.getAuth()!=null)queryWap.eq("auth",params.getAuth());

        //创始人
        if(MyUtils.isNotEmpty(params.getUserId()))queryWap.eq("author_id",params.getUserId());
        //是否可见
        if(params.getIshow()!=null&&params.getIshow()>=0&&params.getIshow()<=1){
            queryWap.eq("ishow",params.getIshow());
        }
        //状态
        if(params.getStatus()!=null&&params.getStatus()>=0&&params.getStatus()<=2){
            queryWap.eq("status",params.getStatus());
        }

        //排序
        queryWap.orderBy(true,"asc".equalsIgnoreCase(params.getOrder()),params.getField());

        //获取范围
        if (MyUtils.isNotEmpty(params.getRangeField())){
            queryWap.between(params.getRangeField(),params.getBetween(),params.getTo());
        }

        //设置分页
        PageHelper.startPage(params.getPage(), params.getSize(),false);
        List<Contest> contests = this.baseMapper.selectList(queryWap);
        //获取报名人数
        for (Contest contest : contests) {

            Object sum = redisTemplate.opsForValue().get(contest.getRedisRegisterPersonKey());
            if(sum!=null){
                contest.setRegisterPerson((Integer) sum);

            }else{
                contest.setRegisterPerson(contestRegisterService.getCountByContest(contest.getId()));
            }
            contest.setPassword(null);
        }
        //求数据条数
        Integer count = this.baseMapper.selectCount(queryWap);

        return new PageResult<Contest>(count.longValue(),contests);
    }



    @Override
    public boolean save(Contest entity) {
        entity.setUpdateTime(new Date());
        entity.setCreateTime(new Date());
        entity.setId(idWorker.nextId().toString());
        entity.setStatus(0);  //设置未开始
        if(entity.getProblems()!=null&&entity.getProblems().size()>0){  //保存题目联系表
            for (ContestProblem problem : entity.getProblems()) {
                problem.setContestId(entity.getId());  //设置比赛id
            }
            try {
                contestProblemService.save(entity.getProblems());
            } catch (RetrunMsgException e) {
                log.error("竞赛题目关联表保存失败，msg:{}",e.getMessage());
                return false;
            }
        }
        //获取最大的code+1
        entity.setCode(this.getMaxCode());
        return super.save(entity);
    }

    private String getMaxCode() {
        String maxCode = this.baseMapper.getMaxCode();
        StringBuilder s = new StringBuilder(String.valueOf(Integer.parseInt(maxCode.substring(3)) + 1));
        while(s.length()<4) s.insert(0, "0");
        return "HPU"+s.toString();
    }

    @Override
    public boolean removeById(Serializable id) {
        redisTemplate.opsForValue().set(id,null);
        log.info("开始执行删除比赛题目的记录");
        contestProblemService.removeByContestId(id);
        return super.removeById(id);
    }

    @Override
    public boolean updateById(Contest entity) {
        redisTemplate.opsForValue().set(entity.getId(),null);
        entity.setUpdateTime(new Date());
        if(entity.getProblems()!=null&&entity.getProblems().size()>0){  //保存题目联系表
            for (ContestProblem problem : entity.getProblems()) {
                problem.setContestId(entity.getId());  //设置比赛id
            }
            try {
                contestProblemService.save(entity.getProblems());
            } catch (RetrunMsgException e) {
                return false;
            }
        }
        //删除榜单缓存
        redisTemplate.opsForValue().set(RankList.getRedisKey(entity.getId()),null);
        return super.updateById(entity);
    }

    @Override
    public Contest getById(Serializable id) {
        Contest byId = null;
        Object o = redisTemplate.opsForValue().get(id);
        if(o!=null)byId = JSON.parseObject(((String) o),Contest.class);
        if(byId==null){
             byId = super.getById(id);
             if(byId==null)return null;
             long st = 5*1000;  //最短5分钟

            //获取题目列表
            List<ContestProblem> list = contestProblemService.listByContestId(id.toString());
            byId.setProblems(list);

            if (byId.getStatus()==1) { //进行中比赛
                st = Math.max(st,byId.getEndTime().getTime()-System.currentTimeMillis());
                st = Math.max(st,1000*60*60*5);  //最长五小时
            }
            redisTemplate.opsForValue().set(id, JSON.toJSONString(byId),st, TimeUnit.MILLISECONDS);
        }
        if(byId.getStartTime().getTime()-System.currentTimeMillis()<0){ //比赛开始
//             System.out.println(byId);
            byId.setStatus(1);
        }
        if(byId.getEndTime().getTime()-System.currentTimeMillis()<0){ //比赛结束
            byId.setStatus(2);
        }
        //更新报名人数
        Object sum = redisTemplate.opsForValue().get(byId.getRedisRegisterPersonKey());
        if(sum!=null){
            byId.setRegisterPerson((Integer) sum);

        }else{
            byId.setRegisterPerson(contestRegisterService.getCountByContest(byId.getId()));
        }
        return byId;
    }
}
